package com.ywl.study.sharding.study06.config.precise;

import com.google.common.collect.Lists;
import com.ywl.study.sharding.common.algorithm.PreciseModuloShardingDatabaseAlgorithm;
import com.ywl.study.sharding.common.algorithm.PreciseModuloShardingTableAlgorithm;
import com.ywl.study.sharding.common.config.ExampleConfiguration;
import com.ywl.study.sharding.study03.util.DataSourceUtil;
import org.apache.shardingsphere.api.config.masterslave.MasterSlaveRuleConfiguration;
import org.apache.shardingsphere.api.config.sharding.KeyGeneratorConfiguration;
import org.apache.shardingsphere.api.config.sharding.ShardingRuleConfiguration;
import org.apache.shardingsphere.api.config.sharding.TableRuleConfiguration;
import org.apache.shardingsphere.api.config.sharding.strategy.StandardShardingStrategyConfiguration;
import org.apache.shardingsphere.shardingjdbc.api.ShardingDataSourceFactory;

import javax.sql.DataSource;
import java.sql.SQLException;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Properties;

/**
 * 主从+分库分表
 */
public class ShardingMasterSlaveConfigurationPrecise implements ExampleConfiguration {
    @Override
    public DataSource getDataSource() throws SQLException {
        ShardingRuleConfiguration configuration=new ShardingRuleConfiguration();
        configuration.getTableRuleConfigs().add(getOrderTableRuleConfiguration());
        configuration.getTableRuleConfigs().add(getOrderItemTableRuleConfiguration());
        configuration.getBindingTableGroups().add("t_order,t_order_item");
        configuration.getBroadcastTables().add("t_address");
        configuration.setDefaultDatabaseShardingStrategyConfig(new StandardShardingStrategyConfiguration("user_id",new PreciseModuloShardingDatabaseAlgorithm()));
        configuration.setDefaultTableShardingStrategyConfig(new StandardShardingStrategyConfiguration("order_id",new PreciseModuloShardingTableAlgorithm()));
        configuration.setMasterSlaveRuleConfigs(getMasterSlaveRuleConfigurations());
        return ShardingDataSourceFactory.createDataSource(createDatasourceMap(),configuration,new Properties());
    }


    private static List<MasterSlaveRuleConfiguration> getMasterSlaveRuleConfigurations(){
        MasterSlaveRuleConfiguration masterSlaveRuleConfig1=new MasterSlaveRuleConfiguration("ds_0","demo_ds_master_0",Arrays.asList("demo_ds_master_0_slave_0","demo_ds_master_0_slave_1"));
        MasterSlaveRuleConfiguration masterSlaveRuleConfig2=new MasterSlaveRuleConfiguration("ds_1","demo_ds_master_1",Arrays.asList("demo_ds_master_1_slave_0","demo_ds_master_1_slave_1"));
        return Lists.newArrayList(masterSlaveRuleConfig1,masterSlaveRuleConfig2);

    }

    private static TableRuleConfiguration getOrderTableRuleConfiguration(){
        TableRuleConfiguration configuration=new TableRuleConfiguration("t_order","ds_${0..1}.t_order_${[0,1]}");
        configuration.setKeyGeneratorConfig(new KeyGeneratorConfiguration("SNOWFLAKE","order_id",getProperties()));
        return configuration;
    }

    private static TableRuleConfiguration getOrderItemTableRuleConfiguration(){
        TableRuleConfiguration configuration=new TableRuleConfiguration("t_order_item","ds_${0..1}.t_order_item_${[0,1]}");
        configuration.setKeyGeneratorConfig(new KeyGeneratorConfiguration("SNOWFLAKE","order_item_id",getProperties()));
        return configuration;
    }

    private static Map<String,DataSource> createDatasourceMap(){
        Map<String,DataSource> result=new HashMap<>();
        result.put("demo_ds_master_0", DataSourceUtil.createDataSource("demo_ds_master_0"));
        result.put("demo_ds_master_0_slave_0",DataSourceUtil.createDataSource("demo_ds_master_0_slave_0"));
        result.put("demo_ds_master_0_slave_1",DataSourceUtil.createDataSource("demo_ds_master_0_slave_1"));
        result.put("demo_ds_master_1", DataSourceUtil.createDataSource("demo_ds_master_1"));
        result.put("demo_ds_master_1_slave_0",DataSourceUtil.createDataSource("demo_ds_master_1_slave_0"));
        result.put("demo_ds_master_1_slave_1",DataSourceUtil.createDataSource("demo_ds_master_1_slave_1"));
        return result;
    }


    private static Properties getProperties(){
        Properties result = new Properties();
        result.setProperty("worker.id", "123");
        return result;
    }
}
